#include <unistd.h>
#include <bits/sockaddr.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <sys/socket.h>

#include "Socket.h"


int Socket::createNonblockSocektOrDie() {
    int fd = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    if (fd < 0) {
        std::cout << "socket create fail" << std::endl;
        abort();
    }
    return fd;
}

void Socket::setReuseAddr(bool on) {
    int opVal = on ? 1 : 0;
    int ret = ::setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &opVal, sizeof(opVal));
    if (ret < 0 && on) {
        std::cout << "setReuseAddr error" << std::endl;
        abort();
    }
}

void Socket::setReusePort(bool on) {
    int opVal = on ? 1 : 0;
    int ret = ::setsockopt(fd_, SOL_SOCKET, SO_REUSEPORT, &opVal, sizeof(opVal));
    if (ret < 0 && on) {
        std::cout << "setReusePort error" << std::endl;
        abort();
    }
}

void Socket::setKeepAlive(bool on) {
    int opVal = on ? 1 : 0;
    int ret = ::setsockopt(fd_, SOL_SOCKET, SO_KEEPALIVE, &opVal, sizeof(opVal));
    if (ret < 0 && on) {
        std::cout << "setKeepAlive error" << std::endl;
        abort();
    }
}

void Socket::bind(InetAddress& addr) {
    ::bind(fd_, addr.getSockAddr(), sizeof(addr));
}

void Socket::listen() {
    int ret = ::listen(fd_, 4096);
    if (ret < 0) {
        std::cout << "listen fail" << std::endl;
        abort();
    }
}

int Socket::accept(InetAddress* peerAddr) {
    socklen_t len = peerAddr->size();
    int connfd = ::accept4(fd_, peerAddr->getSockAddr(), &len, 0);
    return connfd;
}

int Socket::read(char* buf, size_t len) {
    return ::read(fd_, buf, len);
}

int Socket::write(const char* buf, size_t len) {
    return ::write(fd_, buf, len);
}

void Socket::shutdownWrite() {
    int ret = ::shutdown(fd_, SHUT_WR);
    if (ret < 0) {
        std::cout << "shutdownWrite error" << std::endl;
        abort();
    }
}